package top.oauth2.server.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import top.oauth2.common.constant.MessageConstant;
import top.oauth2.entity.security.Menu;
import top.oauth2.entity.security.User;
import top.oauth2.server.entity.SecurityUser;
import top.oauth2.server.mapper.MenuMapper;
import top.oauth2.server.mapper.UserMapper;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author xphu
 * @version 1.0
 * @date 2021/8/27 12:18
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    private final String LOGIN_TYPE_PHONE = "phone";
    private final String LOGIN_TYPE_PC = "pc";

    @Autowired
    UserMapper userMapper;
    @Autowired
    MenuMapper menuMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        String[] strings = username.split(":");
        String type = null;
        if (strings != null && strings.length >1 ){
            type = strings[0];
            username = strings[1];
        }
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        if (!StringUtils.isEmpty(type)){
            if (LOGIN_TYPE_PHONE.equals(type)){
                queryWrapper.eq(User::getPhone, username);
            }
        } else {
            queryWrapper.eq(User::getUsername, username);
        }
        User user = userMapper.selectOne(queryWrapper);
        if (user == null){
            throw new UsernameNotFoundException(MessageConstant.USERNAME_PASSWORD_ERROR);
        }
        // 用户权限或角色集合
        List<Menu> menus = menuMapper.getMenuListByUserName(username, type);
        ArrayList<String> auths = new ArrayList<>();
        menus.forEach(menu -> {
            auths.add(menu.getPermissionValue());
        });
        SecurityUser securityUser = new SecurityUser(user, auths, type);
        if (!securityUser.isEnabled()) {
            throw new DisabledException(MessageConstant.ACCOUNT_DISABLED);
        } else if (!securityUser.isAccountNonLocked()) {
            throw new LockedException(MessageConstant.ACCOUNT_LOCKED);
        } else if (!securityUser.isAccountNonExpired()) {
            throw new AccountExpiredException(MessageConstant.ACCOUNT_EXPIRED);
        } else if (!securityUser.isCredentialsNonExpired()) {
            throw new CredentialsExpiredException(MessageConstant.CREDENTIALS_EXPIRED);
        }
        return securityUser;
    }

}
